package me.ingxin.android.router.route

import android.app.Activity
import android.os.Handler
import android.os.Looper
import androidx.annotation.UiThread
import me.ingxin.android.router.utils.Logger
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicInteger

/**
 * Created by ingxin on 2022/4/20
 */
class RouteHolder private constructor() {

    private val uiHandler by lazy { Handler(Looper.getMainLooper()) }
    private val requestMap = ConcurrentHashMap<String, RouteCallback>()
    private val activityRequestCode = AtomicInteger()
    private val handlerRequestCode = AtomicInteger()

    internal fun holdActivity(request: Request, callback: RouteCallback): String {
        val requestKey = "router_activity_rq#${activityRequestCode.getAndIncrement()}"
        request.putString(START_ACTIVITY_HOLD_KEY, requestKey)
        requestMap[requestKey] = callback
        return requestKey
    }

    internal fun holdHandler(handler: RouteHandler, callback: RouteCallback): String {
        val requestKey = "router_handler_rq#${handlerRequestCode.getAndIncrement()}"
        handler.requestKey = requestKey
        requestMap[requestKey] = callback
        return requestKey
    }

    /**
     * 解除hold功能，移除requestKey对应的callback释放内存。
     * 当发起页面销毁时，应该释放callback，否则会内存泄漏。
     * @param requestKey 缓存key
     * @return false表示调用方法是需要释放的key已经不存在，true表示存在
     */
    @UiThread
    internal fun unHold(requestKey: String): Boolean {
        return if (requestMap.containsKey(requestKey)) {
            Logger.d("unHold [$requestKey], $requestMap")
            requestMap.remove(requestKey)
            true
        } else {
            Logger.d("unHold [$requestKey] not found")
            false
        }
    }

    /**
     * 调试用
     */
    fun printRequestMap() {
        Logger.d("requestMap = $requestMap")
    }

    /**
     * 释放activity的hold功能,并通知回调
     */
    fun releaseActivity(activity: Activity, result: Result) {
        val requestKey = activity.intent?.getStringExtra(START_ACTIVITY_HOLD_KEY) ?: return
        if (Looper.myLooper() == Looper.getMainLooper()) {
            release(requestKey, result, null)
        } else {
            activity.runOnUiThread { release(requestKey, result, null) }
        }
    }

    /**
     * 释放[RouteHandler]的hold功能，并通知回调
     */
    internal fun releaseHandler(handler: RouteHandler, result: Result) {
        val requestKey = handler.requestKey ?: return
        if (Looper.myLooper() == Looper.getMainLooper()) {
            release(requestKey, result) { handler.onRelease() }
        } else {
            uiHandler.post { release(requestKey, result) { handler.onRelease() } }
        }
    }

    @UiThread
    private fun release(requestKey: String, result: Result, block: (() -> Unit)?) {
        if (requestMap.containsKey(requestKey)) {
            val callback = requestMap[requestKey]
            callback?.onResult(result)
            block?.invoke()
            requestMap.remove(requestKey)
        } else {
            Logger.e("requestKey [$requestKey] not found")
        }
    }

    companion object {

        private const val START_ACTIVITY_HOLD_KEY = "start_activity_hold_key"

        @JvmStatic
        val instance by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { RouteHolder() }
    }

}